from PyQt5.QtWidgets import (QWidget, QSlider, QApplication,
                             QHBoxLayout, QVBoxLayout)
from PyQt5.QtCore import QObject, Qt, pyqtSignal
from PyQt5.QtGui import QPainter, QFont, QColor, QPen
import sys


# 定义一个信号类，用于在值改变时发出信号
class Communicate(QObject):
    updateBW = pyqtSignal(int)  # 定义一个信号，用于传递整数值


# 定义一个自定义的QWidget类，用于绘制燃烧效果
class BurningWidget(QWidget):

    def __init__(self):
        super().__init__()  # 调用父类的构造函数
        self.initUI()  # 初始化UI

    def initUI(self):
        self.setMinimumSize(1, 30)  # 设置窗口的最小大小
        self.value = 75  # 初始值
        self.num = [75, 150, 225, 300, 375, 450, 525, 600, 675]  # 刻度值

    def setValue(self, value):
        self.value = value  # 设置当前值

    def paintEvent(self, e):
        qp = QPainter()  # 创建一个QPainter对象
        qp.begin(self)  # 开始绘制
        self.drawWidget(qp)  # 调用绘制方法
        qp.end()  # 结束绘制

    def drawWidget(self, qp):
        MAX_CAPACITY = 700  # 最大容量
        OVER_CAPACITY = 750  # 超过容量的值

        font = QFont('Serif', 7, QFont.Light)  # 设置字体
        qp.setFont(font)  # 应用字体

        size = self.size()  # 获取窗口大小
        w = size.width()  # 宽度
        h = size.height()  # 高度

        step = int(round(w / 10))  # 计算每个刻度的宽度

        till = int(((w / OVER_CAPACITY) * self.value))  # 计算当前值对应的宽度
        full = int(((w / OVER_CAPACITY) * MAX_CAPACITY))  # 计算最大容量对应的宽度

        if self.value >= MAX_CAPACITY:
            # 如果当前值超过最大容量，绘制两个矩形
            qp.setPen(QColor(255, 255, 255))  # 设置画笔颜色
            qp.setBrush(QColor(255, 255, 184))  # 设置画刷颜色
            qp.drawRect(0, 0, full, h)  # 绘制第一个矩形
            qp.setPen(QColor(255, 175, 175))  # 设置画笔颜色
            qp.setBrush(QColor(255, 175, 175))  # 设置画刷颜色
            qp.drawRect(full, 0, till - full, h)  # 绘制第二个矩形
        else:
            # 如果当前值未超过最大容量，绘制一个矩形
            qp.setPen(QColor(255, 255, 255))  # 设置画笔颜色
            qp.setBrush(QColor(255, 255, 184))  # 设置画刷颜色
            qp.drawRect(0, 0, till, h)  # 绘制矩形

        pen = QPen(QColor(20, 20, 20), 1, Qt.SolidLine)  # 设置画笔
        qp.setPen(pen)  # 应用画笔
        qp.setBrush(Qt.NoBrush)  # 设置无画刷
        qp.drawRect(0, 0, w - 1, h - 1)  # 绘制边框

        j = 0
        # 绘制刻度线和刻度值
        for i in range(step, 10 * step, step):
            qp.drawLine(i, 0, i, 5)  # 绘制刻度线
            metrics = qp.fontMetrics()  # 获取字体度量
            fw = metrics.width(str(self.num[j]))  # 计算刻度值的宽度
            x, y = int(i - fw / 2), int(h / 2)  # 计算刻度值的位置
            qp.drawText(x, y, str(self.num[j]))  # 绘制刻度值
            j = j + 1  # 移动到下一个刻度值


# 定义一个主窗口类
class Example(QWidget):

    def __init__(self):
        super().__init__()  # 调用父类的构造函数
        self.initUI()  # 初始化UI

    def initUI(self):
        OVER_CAPACITY = 750  # 超过容量的值

        sld = QSlider(Qt.Horizontal, self)  # 创建一个水平滑块
        sld.setFocusPolicy(Qt.NoFocus)  # 设置滑块不获取焦点
        sld.setRange(1, OVER_CAPACITY)  # 设置滑块的范围
        sld.setValue(75)  # 设置滑块的初始值
        sld.setGeometry(30, 40, 150, 30)  # 设置滑块的位置和大小

        self.c = Communicate()  # 创建信号对象
        self.wid = BurningWidget()  # 创建燃烧效果窗口
        self.c.updateBW[int].connect(self.wid.setValue)  # 连接信号和槽

        sld.valueChanged[int].connect(self.changeValue)  # 连接滑块值改变信号和槽
        hbox = QHBoxLayout()  # 创建一个水平布局
        hbox.addWidget(self.wid)  # 将燃烧效果窗口添加到水平布局
        vbox = QVBoxLayout()  # 创建一个垂直布局
        vbox.addStretch(1)  # 添加一个伸缩项
        vbox.addLayout(hbox)  # 将水平布局添加到垂直布局
        self.setLayout(vbox)  # 设置主窗口的布局

        self.setGeometry(300, 300, 390, 210)  # 设置主窗口的位置和大小
        self.setWindowTitle('Burning widget')  # 设置窗口标题
        self.show()  # 显示窗口

    def changeValue(self, value):
        self.c.updateBW.emit(value)  # 发出信号，传递当前值
        self.wid.repaint()  # 重绘燃烧效果窗口


# 主函数
def main():
    app = QApplication(sys.argv)  # 创建应用程序对象
    ex = Example()  # 创建主窗口对象
    sys.exit(app.exec_())  # 进入主循环


# 程序入口
if __name__ == '__main__':
    main()


def main():
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()